home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 051-075 / scopedisk61 / dme / src / command.c < prev    next >
C/C++ Source or Header  |  1995-03-19  |  19KB  |  730 lines

  1.  
  2. /*
  3.  * COMMAND.C
  4.  *
  5.  *    (C)Copyright 1987 by Matthew Dillon, All Rights Reserved
  6.  *
  7.  * )c             single character (typing)
  8.  * 'c                single character (typing)
  9.  * `string'          string of characters w/ embedded `' allowed!
  10.  * (string)             same thing w/ embedded () allowed!
  11.  * \c             override
  12.  *
  13.  * name arg arg      command name. The arguments are interpreted as strings
  14.  *             for the command.
  15.  *
  16.  * $scanf         macro insert scanf'd variable
  17.  * $filename         macro insert current file name
  18.  *
  19.  * Any string arguments not part of a command are considered to be typed
  20.  * text.
  21.  */
  22.  
  23. #include "defs.h"
  24. #include <stdio.h>
  25.  
  26. #if AREXX
  27. extern int foundcmd;       /* control for implicit ARexx macro invocation   */
  28. extern int cmderr;       /* global command error flag for do_rexx()'s use */
  29. #endif
  30.  
  31. #define CF_COK    1   /*    Can be executed while in command line mode    */
  32. #define CF_PAR    2   /*    ESCIMM special flag.. save rest of command line */
  33.             /*    so it can be executed after user entry        */
  34.  
  35. #define CF_ICO    4   /*    OK to execute if iconified, else uniconify first*/
  36.  
  37. #define BTOCP(val, type)    ((type)((long)val << 2))
  38.  
  39. extern char *breakout();
  40.  
  41. typedef struct {
  42.    char *name;        /* command name      */
  43.    ubyte args;
  44.    ubyte flags;
  45.    int (*func)();   /* function           */
  46. } COMM;
  47.  
  48. extern int  do_map(),       do_unmap(),     do_up(),        do_down(),
  49.         do_left(),      do_right(),     do_return(),    do_bs(),
  50.         do_del(),       do_esc(),       do_downadd(),   do_lastcolumn(),
  51.         do_firstcolumn(),do_edit(),     do_tab(),       do_backtab(),
  52.         do_save(),      do_saveas(),    do_deline(),    do_insline(),
  53.         do_top(),       do_bottom(),    do_source(),    do_firstnb(),
  54.         do_quit(),      do_find(),      do_page(),      do_savetabs(),
  55.         do_split(),     do_goto(),      do_screentop(), do_screenbottom(),
  56.         do_join(),      do_repeat(),    do_tabstop(),   do_insertmode(),
  57.         do_block(),     do_bdelete(),   do_bcopy(),     do_bmove(),
  58.         do_bsave(),     do_wleft(),     do_wright(),    do_remeol(),
  59.         do_savemap(),   do_toggle(),    do_if(),        do_tlate(),
  60.         do_bsource(),   do_findr(),     do_findstr(),   do_newwindow(),
  61.         do_windowparm(),do_resize(),    do_margin(),    do_wordwrap(),
  62.         do_reformat(),  do_execute(),   do_chfilename(),do_scrollup(),
  63.         do_scrolldown(),do_recall(),    do_scanf(),     do_iconify(),
  64.         do_tomouse(),   do_refs(),      do_arpload(),   do_arpsave(),
  65.         do_arpinsfile(),do_setfont(),   do_ignorecase(),do_ctags(),
  66.         do_addpath(),   do_rempath(),   do_set(),       do_setenv(),
  67.         do_unset(),     do_unsetenv(),  do_ipc(),       do_cd();
  68.  
  69. extern int  do_menu(), do_menuclear(), do_menuadd(), do_menudel(),
  70.         do_menudelhdr(), do_menuon(), do_menuoff();
  71.  
  72. extern int  do_null(), do_rx();
  73.  
  74. extern int  do_pushmark(),  do_popmark(),   do_swapmark(),  do_purgemark(),
  75.         do_ping(),      do_pong(),      do_undo();
  76.  
  77. #if AREXX
  78. extern int  do_rx(),        do_rx1(),       do_rx2();
  79. #endif
  80.  
  81. /*============================================================================*/
  82.  
  83. /*
  84.  *  WLEFT/WRIGHT will check command line mode themselves, and thus can
  85.  *  be marked flags=1 even though they can change the line number.
  86.  *
  87.  *  No more than 255 commands may exist unless you change the type of hindex[]
  88.  *
  89.  *  Command names MUST be sorted by their first character
  90.  */
  91.  
  92. unsigned char hindex[26];   /*    alpha hash into table    */
  93.  
  94.     /*      args flags    */
  95.  
  96. COMM Comm[] = {
  97. #ifndef NO_DO2
  98.     "addpath",       1, CF_COK, do_addpath,
  99. #endif
  100.     "arpinsfile",    0,      0, do_arpinsfile,
  101.     "arpload",       0,      0, do_arpload,
  102.     "arpsave",       0,      0, do_arpsave,
  103.     "back",          0, CF_COK, do_bs,
  104.     "backtab",       0, CF_COK, do_backtab,
  105.     "bcopy",         0,      0, do_bcopy,
  106.     "bdelete",       0,      0, do_bdelete,
  107.     "block",         0,      0, do_block,    /* checks com name for mode */
  108.     "bmove",         0,      0, do_bmove,
  109.     "bottom",        0,      0, do_bottom,
  110.     "bs",            0, CF_COK, do_bs,
  111.     "bsave",         1, CF_COK, do_bsave,
  112.     "bsource",       0,      0, do_bsource,
  113.     "cd",            1, CF_COK, do_cd,
  114.     "chfilename",    1,      0, do_chfilename,
  115. #ifndef NO_DO_CTAGS
  116.     "ctags",         0, CF_ICO, do_ctags,
  117. #endif
  118.     "del",           0, CF_COK, do_del,
  119.     "deline",        0,      0, do_deline,
  120.     "down",          0,      0, do_down,
  121.     "downadd",       0,      0, do_downadd,
  122.     "esc",           0, CF_COK, do_esc,
  123.     "escimm",        1, CF_PAR, do_esc,
  124.     "execute",       1, CF_ICO, do_execute,
  125.     "find",          1,      0, do_find,     /* checks com name for mode */
  126.     "findr",         2,      0, do_findr,    /* checks com name for mode */
  127.     "findstr",       1, CF_COK, do_findstr,  /* checks com name for mode */
  128.     "first",         0, CF_COK, do_firstcolumn,
  129.     "firstnb",       0, CF_COK, do_firstnb,
  130.     "goto",          1,      0, do_goto,
  131.     "height",        1, CF_COK, do_windowparm,
  132.     "iconify",       0, CF_ICO, do_iconify,
  133.     "if",            2, CF_COK, do_if,
  134.     "ifelse",        3, CF_COK, do_if,
  135.     "ignorecase",    1, CF_COK, do_ignorecase,
  136.     "insertmode",    1, CF_COK, do_insertmode,
  137.     "insfile",       1,      0, do_edit,
  138.     "insline",       0,      0, do_insline,
  139.     "ipc",           3, CF_COK, do_ipc,
  140.     "join",          0,      0, do_join,
  141.     "last",          0, CF_COK, do_lastcolumn,
  142.     "left",          0, CF_COK, do_left,
  143.     "leftedge",      1, CF_COK, do_windowparm,
  144.     "map",           2, CF_COK, do_map,
  145.     "margin",        1, CF_COK, do_margin,
  146.     "menuon",        0,      0, do_menuon,
  147.     "menuoff",       0,      0, do_menuoff,
  148.     "menuadd",       3,      0, do_menuadd,
  149.     "menudel",       2,      0, do_menudel,
  150.     "menudelhdr",    1,      0, do_menudelhdr,
  151.     "menuclear",     0,      0, do_menuclear,
  152.     "newfile",       1,      0, do_edit,     /* checks com name for mode */
  153.     "newwindow",     0, CF_ICO, do_newwindow,
  154.     "next",          0,      0, do_find,
  155.     "nextr",         0,      0, do_findr,
  156.     "null",          0, CF_COK, do_null,
  157.     "pagedown",      0,      0, do_page,
  158.     "pageset",       1,      0, do_page,
  159.     "pageup",        0,      0, do_page,
  160.     "ping",          1, CF_ICO, do_ping,
  161.     "pong",          1,      0, do_pong,
  162.     "prev",          0,      0, do_find,
  163.     "prevr",         0,      0, do_findr,
  164.     "popmark",       0,      0, do_popmark,
  165.     "purgemark",     0,      0, do_purgemark,
  166.     "pushmark",      0,      0, do_pushmark,
  167.     "quit",          0, CF_ICO, do_quit,
  168.     "recall",        0, CF_COK, do_recall,
  169. #ifndef NO_DO_REF
  170.     "ref",           0,      0, do_refs,
  171. #endif
  172.     "reformat",      0,      0, do_reformat,
  173.     "remeol",        0, CF_COK, do_remeol,
  174. #ifndef NO_DO2
  175.     "rempath",       1, CF_COK, do_rempath,
  176. #endif
  177.     "repeat",        2, CF_ICO|CF_COK, do_repeat,
  178.     "repstr",        1, CF_COK, do_findstr,
  179.     "resettoggle",   1, CF_COK, do_toggle,
  180.     "resize",        2,      0, do_resize,
  181.     "return",        0, CF_COK, do_return,   /* special meaning in command line mode */
  182.     "right",         0, CF_COK, do_right,
  183. #if AREXX
  184.     "rx",            1,      0, do_rx,       /* explicit ARexx macro invocation      */
  185.     "rx1",           2,      0, do_rx1,      /* explicit, with 1 arg  to ARexx macro */
  186.     "rx2",           3,      0, do_rx2,      /* explicit, with 2 args to ARexx macro */
  187. #endif
  188.     "saveas",        1, CF_ICO|CF_COK, do_saveas,
  189.     "savemap",       1, CF_ICO|CF_COK, do_savemap,  /* checks com name for mode */
  190.     "saveold",       0, CF_ICO|CF_COK, do_save,
  191.     "savesmap",      1, CF_ICO|CF_COK, do_savemap,
  192.     "savetabs",      1, CF_ICO|CF_COK, do_savetabs,
  193.     "scanf",         1, CF_COK, do_scanf,
  194.     "screenbottom",  0,      0, do_screenbottom,
  195.     "screentop",     0,      0, do_screentop,
  196.     "scrollup",      0,      0, do_scrollup,
  197.     "scrolldown",    0,      0, do_scrolldown,
  198.     "set",           2, CF_ICO|CF_COK, do_set,
  199.     "setenv",        2, CF_ICO|CF_COK, do_setenv,
  200.     "setfont",       2,      0, do_setfont,
  201.     "settoggle",     1, CF_COK, do_toggle,
  202.     "source",        1, CF_COK, do_source,
  203.     "split",         0,      0, do_split,
  204.     "swapmark",      0,      0, do_swapmark,
  205.     "tab",           0, CF_COK, do_tab,
  206.     "tabstop",       1, CF_COK, do_tabstop,
  207.     "tlate",         1, CF_COK, do_tlate,
  208.     "tmpheight",     1, CF_COK, do_windowparm,
  209.     "tmpwidth",      1, CF_COK, do_windowparm,
  210.     "toggle",        1, CF_COK, do_toggle,
  211.     "tomouse",       0,      0, do_tomouse,
  212.     "top",           0,      0, do_top,
  213.     "topedge",       1, CF_COK, do_windowparm,
  214.     "unblock",       0,      0, do_block,
  215.     "undo",          0,      0, do_undo,
  216.     "unmap",         1, CF_ICO|CF_COK, do_unmap,
  217.     "unset",         1, CF_ICO|CF_COK, do_unset,
  218.     "unsetenv",      1, CF_ICO|CF_COK, do_unsetenv,
  219.     "up",            0,      0, do_up,
  220.     "while",         2, CF_ICO|CF_COK, do_if,
  221.     "width",         1, CF_COK, do_windowparm,
  222.     "wleft",         0, CF_COK, do_wleft,
  223.     "wordwrap",      1, CF_COK, do_wordwrap,
  224.     "wright",        0, CF_COK, do_wright,
  225.     NULL, 0, 0, NULL
  226. };
  227.  
  228. init_command()
  229. {
  230.     register short hi;
  231.     register COMM *comm;
  232.  
  233.     hi = sizeof(Comm)/sizeof(Comm[0]) - 2;
  234.     comm = Comm + hi;
  235.  
  236.     while (hi >= 0) {
  237.     hindex[comm->name[0] - 'a'] = hi;
  238.     --hi;
  239.     --comm;
  240.     }
  241. }
  242.  
  243. #define MAXIA    5
  244.  
  245. do_command(str)
  246. char *str;
  247. {
  248.     register char *arg;
  249.     char *aux1, *aux2;
  250.     char *repstr[MAXIA];
  251.     char quoted;
  252.     short repi = 0;
  253.     register short i, j;
  254.     static int level;
  255.  
  256.     if (++level > 20) {
  257.     title("Recursion Too Deep!");
  258.     --level;
  259. #if AREXX
  260.     foundcmd = 1;    /* to prevent us from trying an ARexx macro */
  261. #endif
  262.     return(0);
  263.     }
  264.     while (arg = breakout(&str, "ed, &aux1)) {
  265.     if (quoted) {
  266.         if (Ep->iconmode)
  267.         uniconify();
  268.         text_write(arg);
  269.         goto loop;
  270.     }
  271.     for (i = 0; arg[i]; ++i) {
  272.         if (arg[i] >= 'A' && arg[i] <= 'Z')
  273.         arg[i] += 'a' - 'A';
  274.     }
  275.  
  276.     if (arg[0] >= 'a' && arg[0] <= 'z') {
  277.         register COMM *comm = &Comm[hindex[arg[0]-'a']];
  278.         for (; comm->name && comm->name[0] == arg[0]; ++comm) {
  279.         if (strcmp(arg, comm->name) == 0) {
  280. #if AREXX
  281.             foundcmd = 1;
  282. #endif
  283.             av[0] = (ubyte *)comm->name;
  284.             for (j = 1; j <= comm->args; ++j) {
  285.             av[j] = (ubyte *)breakout(&str, "ed, &aux2);
  286.             if (aux2) {
  287.                 if (repi == MAXIA) {
  288.                 free(aux2);
  289.                 title("Command too complex");
  290.                 goto fail;
  291.                 } else {
  292.                 repstr[repi++] = aux2;
  293.                 }
  294.             }
  295.             if (!av[j]) {
  296.                 title("Bad argument");
  297.                 goto fail;
  298.             }
  299.             }
  300.             av[j] = NULL;   /* end of arglist */
  301.             if ((comm->flags & CF_COK) || !Comlinemode) {
  302.             if (comm->flags & CF_PAR) {
  303.                 if (Partial)
  304.                 free(Partial);
  305.                 Partial = (char *)malloc(strlen(str)+1);
  306.                 strcpy(Partial, str);
  307.                 str += strlen(str);     /*  skip string */
  308.             }
  309.             if (Ep->iconmode && !(comm->flags & CF_ICO))
  310.                 uniconify();
  311.             (*comm->func)(-1);
  312.             }
  313.             if (Abortcommand)
  314.             goto fail;
  315.             goto loop;
  316.         }
  317.         }
  318.     }
  319.  
  320.     /* Command not found, check for macro    */
  321.  
  322.     {
  323.         char *str;
  324.         int ret;
  325.         if ((str = keyspectomacro(arg)) || (str = menutomacro(arg))) {
  326.         str = (char *)strcpy(malloc(strlen(str)+1), str);
  327.         ret = do_command(str);
  328.         free(str);
  329. #if AREXX
  330.         if (ret) {
  331.             foundcmd = 1;   /* dunno about this yet for ARexx macros */
  332.             goto loop;
  333.         }
  334. #else
  335.         if (ret)
  336.             goto loop;
  337. #endif
  338.         goto fail;
  339.         }
  340.     }
  341.  
  342.     /* Command still not found, check for public macro  */
  343.     /* code to be added */
  344.  
  345. #if AREXX
  346.     do_rxImplied(arg, str);
  347. #else
  348.     title("Unknown Command");
  349. #endif
  350. fail:
  351.     --level;
  352.     while (--repi >= 0)
  353.         free(repstr[repi]);
  354.     if (aux1)
  355.         free(aux1);
  356.     return(0);
  357. loop:
  358.     if (aux1)
  359.         free(aux1);
  360.     }
  361.     --level;
  362.     while (--repi >= 0)
  363.     free(repstr[repi]);
  364.     return(1);
  365. }
  366.  
  367. do_null()
  368. {
  369. }
  370.  
  371. do_source()
  372. {
  373.     char buf[256];
  374.     long xfi;
  375.     register char *str;
  376.     long oldlock = CurrentDir(DupLock(Ep->dirlock));
  377.  
  378.     if (xfi = xfopen(av[1], "r", 512)) {
  379.     while (xfgets(xfi, buf, 256) >= 0) {
  380.         if (buf[0] == '#')
  381.         continue;
  382.         for (str = buf; *str; ++str) {
  383.         if (*str == 9)
  384.             *str = ' ';
  385.         }
  386.         do_command(buf);
  387.     }
  388.     xfclose(xfi);
  389.     } else {
  390.     if (av[0])
  391.         title("File not found");
  392.     }
  393.     UnLock(CurrentDir(oldlock));
  394. }
  395.  
  396.  
  397. do_quit()
  398. {
  399.     extern char Quitflag;
  400.  
  401.     Quitflag = 1;
  402. }
  403.  
  404. do_execute()
  405. {
  406.     long oldlock = CurrentDir(Ep->dirlock);
  407.     long NilFH = Open("null:", 1006);
  408.     PROC *proc = (PROC *)FindTask(NULL);
  409.  
  410.     if (NilFH) {
  411.     proc->pr_ConsoleTask = (APTR)BTOCP(NilFH, struct FileHandle *)->fh_Port;
  412.     Execute(av[1], NilFH, NilFH);
  413.     Close(NilFH);
  414.     } else {
  415.     title("NULL: device required for (execute)");
  416.     }
  417.     CurrentDir(oldlock);
  418. }
  419.  
  420. /*
  421.  * repeat X command
  422.  *
  423.  * Since repeat takes up 512+ stack, it should not be nested more than
  424.  * twice.
  425.  *
  426.  * (if X is not a number it can be abbr. with 2 chars)
  427.  *
  428.  * X =    N     -number of repeats
  429.  *    line  -current line # (lines begin at 1)
  430.  *    lbot  -#lines to the bottom, inc. current
  431.  *    cleft -column # (columns begin at 0)
  432.  *        (thus is also chars to the left)
  433.  *    cright-#chars to eol, including current char
  434.  *    tr    -#char positions to get to next tab stop
  435.  *    tl    -#char positions to get to next backtab stop
  436.  */
  437.  
  438. #define SC(a,b) ((a)<<8|(b))
  439.  
  440. do_repeat()
  441. {
  442.     register ubyte *ptr = av[1];
  443.     register unsigned long n;
  444.     char buf1[256];
  445.     char buf2[256];
  446.  
  447.     breakreset();
  448.     strcpy(buf1, av[2]);
  449.     switch((ptr[0]<<8)+ptr[1]) {
  450.     case SC('l','i'):
  451.     n = text_lineno();
  452.     break;
  453.     case SC('l','b'):
  454.     n = text_lines() - text_lineno() + 1;
  455.     break;
  456.     case SC('c','l'):
  457.     n = text_colno();
  458.     break;
  459.     case SC('c','r'):
  460.     n = text_cols() - text_colno();
  461.     break;
  462.     case SC('t','r'):
  463.     n = text_tabsize()-(text_colno() % text_tabsize());
  464.     break;
  465.     case SC('t','l'):
  466.     n = text_colno() % text_tabsize();
  467.     if (n == 0)
  468.         n = text_tabsize();
  469.     break;
  470.     default:
  471.     n = atoi(av[1]);
  472.     break;
  473.     }
  474.     while (n > 0) {
  475.     strcpy(buf2, buf1);
  476.     if (do_command(buf2) == 0 || breakcheck()) {
  477.         Abortcommand = 1;
  478.         break;
  479.     }
  480.     --n;
  481.     }
  482. }
  483.  
  484. /*
  485.  *  BREAKOUT()
  486.  *
  487.  *  Break out the next argument.  The argument is space delimited and
  488.  *  might be quoted with `' or (), or single quoted as 'c or )c
  489.  *
  490.  *  Also:    $var        -variable insertion
  491.  *        ^c        -control character
  492.  */
  493.  
  494. char *
  495. breakout(ptr, quoted, paux)
  496. register char **ptr;
  497. char **paux;
  498. char *quoted;
  499. {
  500.     register char *str = *ptr;
  501.     char *base;
  502.     short count = 0;
  503.     char opc = 0;
  504.     char clc = 0;
  505.     char immode = 0;
  506.     char isaux = 0;
  507.     char buf[256];
  508.     short di = 0;
  509.  
  510.     *quoted = 0;
  511.     *paux = NULL;
  512.     while (*str == ' ')
  513.     ++str;
  514.     if (!*str)
  515.     return(NULL);
  516.  
  517.     *ptr = str;
  518.     base = str;
  519.     while (*str) {
  520.     if (immode) {
  521.         if (di != sizeof(buf)-1)
  522.         buf[di++] = *str;
  523.         ++str;
  524.         continue;
  525.     }
  526.     if (count == 0) {
  527.         if (*str == ' ')
  528.         break;
  529.         if (*str == '\'' || *str == ')')
  530.         clc = *str;
  531.         if (*str == '`') {
  532.         opc = '`';
  533.         clc = '\'';
  534.         }
  535.         if (*str == '(') {
  536.         opc = '(';
  537.         clc = ')';
  538.         }
  539.     }
  540.     if (*str == opc) {
  541.         ++count;
  542.         if (str == *ptr) {
  543.         *quoted = 1;
  544.         base = ++str;
  545.         continue;
  546.         }
  547.     }
  548.     if (*str == clc) {
  549.         --count;
  550.         if (count == 0 && *quoted)     /*  end of argument     */
  551.         break;
  552.         if (str == *ptr && count < 0) {
  553.         immode = 1;
  554.         *quoted = 1;
  555.         base = ++str;
  556.         continue;
  557.         }
  558.     }
  559.  
  560.     /*
  561.      *  $varname $(varname) $`varname'.  I.E. three forms are allowed,
  562.      *  which allows one to insert the string almost anywhere.  The
  563.      *  first form names are limited to alpha-numerics, '-', and '_'.
  564.      */
  565.  
  566.     if (*str == '$') {
  567.         register char *ptr;
  568.         char *tmpptr;
  569.         char c, ce;
  570.         short len;
  571.  
  572.         ce = 0;                /*    first form  */
  573.         ++str;                /*    skip $        */
  574.         if (*str == '(') {              /*  second form */
  575.         ce = ')';
  576.         ++str;
  577.         } else if (*str == '`') {       /*  third form  */
  578.         ce = '\'';
  579.         ++str;
  580.         }
  581.         ptr = str;                /*    start of varname    */
  582.         if (ce) {                       /*  until end char OR   */
  583.         while (*ptr && *ptr != ce)
  584.             ++ptr;
  585.         } else {                /*    smart end-varname   */
  586.         while ((*ptr >= 'a' && *ptr <= 'z') ||
  587.             (*ptr >= 'A' && *ptr <= 'Z') ||
  588.             (*ptr >= '0' && *ptr <= '9') ||
  589.             *ptr == '-' || *ptr == '_' ) {
  590.             ++ptr;
  591.         }
  592.         }
  593.         len = ptr - str;            /*    length of variable  */
  594.  
  595.         c = *ptr; *ptr = 0;         /*    temp. terminate \0  */
  596.         if (strcmp(str, "scanf") == 0) {
  597.         *ptr = c;
  598.         isaux = 1;
  599.         if (di + strlen(String) < sizeof(buf)-1) {
  600.             strcpy(buf + di, String);
  601.             di += strlen(buf + di);
  602.         }
  603.         str += len;            /*    next string pos     */
  604.         if (ce)
  605.             ++str;
  606.         continue;
  607.         }
  608.         if (strcmp(str, "fpath") == 0) {
  609.         register short i;
  610.         for (i = strlen(Ep->Name); i >= 0; --i) {
  611.             if (Ep->Name[i] == ':' || Ep->Name[i] == '/')
  612.             break;
  613.         }
  614.         ++i;
  615.         *ptr = c;
  616.         isaux = 1;
  617.         if (di + i < sizeof(buf)-1) {
  618.             BMov(Ep->Name, buf + di, i);
  619.             di += i;
  620.             buf[di] = 0;
  621.         }
  622.         str += len;
  623.         if (ce)
  624.             ++str;
  625.         continue;
  626.         }
  627.         if (strcmp(str, "fname") == 0) {
  628.         register short i;
  629.         short j;
  630.         for (i = strlen(Ep->Name); i >= 0; --i) {
  631.             if (Ep->Name[i] == ':' || Ep->Name[i] == '/')
  632.             break;
  633.         }
  634.         ++i;
  635.         j = strlen(Ep->Name + i);
  636.         *ptr = c;
  637.         isaux = 1;
  638.         if (di + j < sizeof(buf)-1) {
  639.             BMov(Ep->Name + i, buf + di, j);
  640.             di += j;
  641.             buf[di] = 0;
  642.         }
  643.         str += len;
  644.         if (ce)
  645.             ++str;
  646.         continue;
  647.         }
  648.         if (strcmp(str, "filename") == 0) {
  649.         *ptr = c;
  650.         isaux = 1;
  651.         if (di + strlen(Ep->Name) < sizeof(buf)-1) {
  652.             strcpy(buf + di, Ep->Name);
  653.             di += strlen(buf + di);
  654.         }
  655.         str += len;
  656.         if (ce)
  657.             ++str;
  658.         continue;
  659.         }
  660.         if (strcmp(str, "colno") == 0) {
  661.         *ptr = c;
  662.         isaux = 1;
  663.         if (di < sizeof(buf)-8) {
  664.             sprintf(buf + di, "%ld", Ep->Column + 1);
  665.             di += strlen(buf + di);
  666.         }
  667.         str += len;
  668.         if (ce)
  669.             ++str;
  670.         continue;
  671.         }
  672.         if (strcmp(str, "lineno") == 0) {
  673.         *ptr = c;
  674.         isaux = 1;
  675.         if (di < sizeof(buf)-8) {
  676.             sprintf(buf + di, "%ld", Ep->Line + 1);
  677.             di += strlen(buf + di);
  678.         }
  679.         str += len;
  680.         if (ce)
  681.             ++str;
  682.         continue;
  683.         }
  684.         if (tmpptr = getvar(str)) {
  685.         ptr = tmpptr;
  686.         str[len] = c;
  687.         isaux = 1;
  688.         if (di + strlen(ptr) < sizeof(buf)-1) {
  689.             strcpy(buf + di, ptr);
  690.             di += strlen(buf + di);
  691.         }
  692.         str += len;
  693.         if (ce)
  694.             ++str;
  695.         free(ptr);
  696.         continue;
  697.         }
  698.         *ptr = c;
  699.         --str;
  700.         if (ce)
  701.         --str;
  702.     }
  703.     if (*str == '^' && (str[1] & 0x1F)) {
  704.         ++str;
  705.         *str &= 0x1F;
  706.         isaux = 1;
  707.     }
  708.     if (*str == '\\' && str[1]) {
  709.         ++str;
  710.         isaux = 1;
  711.     }
  712.     buf[di++] = *str++;
  713.     }
  714.     buf[di++] = 0;
  715.     if (isaux) {
  716.     *paux = malloc(di);
  717.     strcpy(*paux, buf);
  718.     base = *paux;
  719.     }
  720.     if (*str) {             /*  space ended */
  721.     *str = '\0';
  722.     *ptr = str + 1;     /*    next arg    */
  723.     } else {
  724.     *ptr = str;        /*    last arg    */
  725.     }
  726.     return(base);
  727. }
  728.  
  729.  
  730.